#include "CoordinateX.h"

#include "CatanClassContractException.h"
#include "CatanImpossibleException.h"

namespace catan
{

/*static*/ std::vector<CoordinateX::Enum_CoordinateX> CoordinateX::vectorOfPossibleEnumValues;

/*static*/ const std::vector<CoordinateX::Enum_CoordinateX> &CoordinateX::getVectorOfPossibleEnumValues()
{
	if (vectorOfPossibleEnumValues.empty())
	{
		vectorOfPossibleEnumValues.push_back(X0);
		vectorOfPossibleEnumValues.push_back(X1);
		vectorOfPossibleEnumValues.push_back(X2);
		vectorOfPossibleEnumValues.push_back(X3);
		vectorOfPossibleEnumValues.push_back(X4);
		vectorOfPossibleEnumValues.push_back(X5);
		vectorOfPossibleEnumValues.push_back(X6);
	}
	return vectorOfPossibleEnumValues;
}

/*static*/ bool CoordinateX::canInit(Enum_CoordinateX enumX)
{
	const std::vector<Enum_CoordinateX> enumValues = CoordinateX::getVectorOfPossibleEnumValues();
	for (std::vector<Enum_CoordinateX>::const_iterator enumValueIterator = enumValues.begin(); enumValueIterator != enumValues.end(); ++enumValueIterator)
	{
		if (enumX == *enumValueIterator)
		{
			return true;
		}
	}
	return false;
}

/*explicit*/ CoordinateX::CoordinateX(Enum_CoordinateX enumX): enumX(enumX)
{
	if (!CoordinateX::canInit(enumX))
	{
		throw CatanClassContractException(__FILE__, __LINE__, "CoordinateX::canInit(...) with constructor arguments should be true before creating instance.");
	}
}

CoordinateX::Enum_CoordinateX CoordinateX::getEnum() const
{
	return enumX;
}

bool CoordinateX::canCreateNeighbor(VerticalCardinal verticalCardinal) const
{
	switch (verticalCardinal.getEnum())
	{
	case VerticalCardinal::VERTICAL_TR:
	case VerticalCardinal::VERTICAL_BR:
		return CoordinateX::canInit(static_cast<Enum_CoordinateX>(enumX+1));
	case VerticalCardinal::VERTICAL_TL:
	case VerticalCardinal::VERTICAL_BL:
		return CoordinateX::canInit(static_cast<Enum_CoordinateX>(enumX-1));
	case VerticalCardinal::VERTICAL_TC:
	case VerticalCardinal::VERTICAL_BC:
		return true;
	default:
		return false;
	}
}

CoordinateX CoordinateX::createNeighbor(VerticalCardinal verticalCardinal) const
{
	if (!canCreateNeighbor(verticalCardinal))
	{
		throw CatanClassContractException(__FILE__, __LINE__, "<coordinateX>.canCreateNeighbor(...) should be true before using <coordinateX>.createNeighbor(...).");
	}
	switch (verticalCardinal.getEnum())
	{
	case VerticalCardinal::VERTICAL_TR:
	case VerticalCardinal::VERTICAL_BR:
		return CoordinateX(static_cast<Enum_CoordinateX>(enumX + 1));
	case VerticalCardinal::VERTICAL_TL:
	case VerticalCardinal::VERTICAL_BL:
		return CoordinateX(static_cast<Enum_CoordinateX>(enumX - 1));
	case VerticalCardinal::VERTICAL_TC:
	case VerticalCardinal::VERTICAL_BC:
		return *this;
	default:
		throw CatanImpossibleException(__FILE__, __LINE__, "Unexpected exception. <coordinateX>.canCreateNeighbor(...) should have thrown earlier.");
	}
}

bool CoordinateX::operator==(const CoordinateX &other) const
{
	return (enumX == other.enumX);
}

bool CoordinateX::operator<(const CoordinateX &other) const
{
	return (enumX < other.enumX);
}

CoordinateX& CoordinateX::operator=(const CoordinateX& other)
{
    if (this != &other)
    {
        enumX = other.enumX;
    }
    return *this;	
}

}
